package cn.rengy.isql;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import java.util.List;
import java.util.Map;

@Slf4j
//@ConditionalOnBean(DataSourceAutoConfiguration.class)
public class NamedSqlDao {

	private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
	@Autowired
	public NamedSqlDao(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
		this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
	}

	public <T> List<T> querySingleColumnForList(String sql, SqlParameterSource sqlParameterSource, Class<T> elementType){
		if(log.isDebugEnabled()){
			log.debug("Executing named SQL:\n{}\n:{}",sql,sqlParameterSource.toString());
		}
		return this.namedParameterJdbcTemplate.queryForList(sql,sqlParameterSource,elementType);
	}
	public int update(String sql,SqlParameterSource sqlParameterSource){
		if(log.isDebugEnabled()){
			log.debug("Executing named SQL:\n{}\n:{}",sql,sqlParameterSource.toString());
		}
		int i= namedParameterJdbcTemplate.update(sql, sqlParameterSource);
		log.debug("{} rows affected",i);
		return i;
	}
	/**
	 * 返回last_insert_id
	 */
	public Number updateReturnGeneratedKeys(String sql,SqlParameterSource sqlParameterSource){
		if(log.isDebugEnabled()){
			log.debug("Executing named SQL:\n{}\n:{}",sql,sqlParameterSource.toString());
		}
		KeyHolder keyHolder = new GeneratedKeyHolder(); 
		namedParameterJdbcTemplate.update(sql,sqlParameterSource, keyHolder);
		return keyHolder.getKey();
	}
	/**
	 * 查询
	 * 通过name绑定参数
	 */
	public <T> T querySingleColumn(String sql,SqlParameterSource sqlParameterSource,Class<T> requiredType){
		if(log.isDebugEnabled()){
			log.debug("Executing named SQL:\n{}\n:{}",sql,sqlParameterSource.toString());
		}
		try{
			return namedParameterJdbcTemplate.queryForObject(sql, sqlParameterSource, new SingleColumnRowMapper<>(requiredType));
		}catch(EmptyResultDataAccessException ignored){}
		return null;
	}
	/**
	 * namedParameter批量更新
	 */
	public int[] batchUpdate(String sql,SqlParameterSource[] batchArgs){
		if(log.isDebugEnabled()){
			log.debug("Batch Executing named SQL:\n{}",sql);
			for(int i=0;i<batchArgs.length;i++) {
				SqlParameterSource arg=batchArgs[i];
				log.debug("BatchParameter[{}]:{}",i,arg.toString());
			}
		}
		return this.namedParameterJdbcTemplate.batchUpdate(sql, batchArgs);
	}
	/**
	 * 通过name绑定参数
	 */
	public List<Map<String,Object>> queryForList(String sql,SqlParameterSource paramSource){
		if(log.isDebugEnabled()){
			log.debug("Executing named SQL:\n{}\n:{}",sql,paramSource.toString());
		}
		return namedParameterJdbcTemplate.query( sql,  paramSource, new ColumnMapCamelCaseRowMapper());
		//return namedParameterJdbcTemplate.queryForList(sql, paramSource);
	}

	public Map<String,Object> queryForMap(String sql,SqlParameterSource sqlParameterSource){
		if(log.isDebugEnabled()){
			log.debug("Executing named SQL:\n{}\n:{}",sql,sqlParameterSource.toString());
		}
		try{
			return namedParameterJdbcTemplate.queryForObject(sql, sqlParameterSource,new ColumnMapCamelCaseRowMapper());
			//return namedParameterJdbcTemplate.queryForMap(sql, sqlParameterSource);
		}catch(EmptyResultDataAccessException ignored){

		}
		return null;
	}


	public <T> T queryForBean(String sql,SqlParameterSource sqlParameterSource,Class<T> elementType){
		if(log.isDebugEnabled()){
			log.debug("Executing named SQL:\n{}\n:{}",sql,sqlParameterSource.toString());
		}
		try{
			return namedParameterJdbcTemplate.queryForObject(sql, sqlParameterSource, new BeanPropertyRowMapper<T>(elementType));
		}catch(EmptyResultDataAccessException e){
			return null;
		}
	}

	public <T> List<T> queryBeanForList(String sql, SqlParameterSource sqlParameterSource, Class<T> elementType){
		if(log.isDebugEnabled()){
			log.debug("Executing named SQL:\n{}\n:{}",sql,sqlParameterSource.toString());
		}
		return namedParameterJdbcTemplate.query(sql, sqlParameterSource, new BeanPropertyRowMapper<T>(elementType));
	}
	
}
